package com.pay.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.pay.beans.ReturnContent;
import com.pay.commons.utils.lang.DateUtils;
import com.pay.constants.RedisKeyConstants;
import com.pay.constants.RetConstants;
import com.pay.dubbo.wx.WxServiceFacade;
import com.pay.entity.wx.WxPayBill;
import com.pay.entity.wx.WxPayDetail;
import com.pay.enums.SuccessFail;
import com.pay.mapper.wx.WxPayBillMapper;
import com.pay.service.WxPayBillService;
import com.pay.service.WxPayDetailService;
import com.pay.util.RedisUtil;
import com.pay.util.UUIDHexGenerator;

@Service("wxPayBillService")
public class WxPayBillServiceImpl implements WxPayBillService {
	private Logger logger = LoggerFactory.getLogger(WxPayBillServiceImpl.class);

	@Resource
	private WxPayBillMapper wxPayBillMapper;
	@Resource
	private WxServiceFacade wxServiceFacade;
	@Resource
	private WxPayDetailService wxPayDetailService;

	@Override
	public WxPayBill findPayBillByOutTradeNo(String outerAppId, String outerTradeNo) {
		return wxPayBillMapper.findPayBillByOutTradeNo(outerAppId, outerTradeNo);
	}

	@Override
	public void insert(WxPayBill wxPayBill) {
		wxPayBillMapper.insert(wxPayBill);
	}

	@Override
	public WxPayBill findPayBillByPartnerTradeNo(String partnerTradeNo) {
		return wxPayBillMapper.findPayBillByPartnerTradeNo(partnerTradeNo);
	}

	@Override
	public void update(WxPayBill wxPayBill) {
		wxPayBillMapper.update(wxPayBill);
	}

	@Override
	public ReturnContent<Object> insertPayBill(String outerAppid, String openId, String amount, String ip, String desc,
			String outerOpenid, String outerTradeNo) {
		String status = RetConstants.SUCCESS;// 返回编号
		String msg = "";// 返回消息
		String tradeNo = "";
		try {
			WxPayBill payBill = this.findPayBillByOutTradeNo(outerAppid, outerTradeNo);
			if (payBill != null && "SUCCESS".equals(payBill.getReturnCode())
					&& "SUCCESS".equals(payBill.getResultCode())) {
				return new ReturnContent<>(RetConstants.SUCCESS, "已领取成功");
			}
			WxPayBill wxPayBill = new WxPayBill();
			UUIDHexGenerator uuidGenerator = UUIDHexGenerator.getInstance();
			wxPayBill.setOuterAppid(outerAppid);// 外部商户编号
			wxPayBill.setOuterOpenid(outerOpenid);// 外部商户openid
			wxPayBill.setOuterTradeNo(outerTradeNo);// 外部商户订单号
			String today = new SimpleDateFormat("yyyyMMdd").format(new Date());
			String code = uuidGenerator.createCode(10);
//			String mchid = WeixinConstants.lzzymchid;// 商户号

			tradeNo = payBill == null ? (//mchid +
					today + code) : payBill.getPartnerTradeNo();
			wxPayBill.setPartnerTradeNo(tradeNo);// 商户订单号
			wxPayBill.setOpenid(openId);// 乐众微信授权用户openid
			wxPayBill.setNonceStr(uuidGenerator.generate());// 获取uuid作为随机字符串
			wxPayBill.setCheckName("NO_CHECK");// 校验用户姓名选项，默认为不校验
			wxPayBill.setAmount(new BigDecimal(amount));// 打款金额
			wxPayBill.setDesc(desc);// 企业付款描述
			wxPayBill.setIp(ip);// 操作ip
			wxPayBill.setReturnCode(SuccessFail.FAIL.name());// 通信标示默认FAIL
			wxPayBill.setResultCode(SuccessFail.FAIL.name());// 下单业务结果默认FAIL

//			EnterPrisePaymentBean enterPrisePaymentBean = new EnterPrisePaymentBean();
//
//			enterPrisePaymentBean.setNonce_str(wxPayBill.getNonceStr());// 随机字符串
//			enterPrisePaymentBean.setMch_appid(WeixinConstants.lzzymch_appid);// 支付appid
//			enterPrisePaymentBean.setMchid(WeixinConstants.lzzymchid);// 商户号
//			enterPrisePaymentBean.setPartner_trade_no(wxPayBill.getPartnerTradeNo());// 商户订单号
//			enterPrisePaymentBean.setOpenid(wxPayBill.getOpenid());// 乐众微信授权用户openid
//			enterPrisePaymentBean.setCheck_name("NO_CHECK");// 校验用户姓名选项，默认为不校验
//			enterPrisePaymentBean
//					.setAmount(String.valueOf(wxPayBill.getAmount().multiply(new BigDecimal(100)).toBigInteger()));// 企业付款金额，单位为分
//			enterPrisePaymentBean.setDesc(wxPayBill.getDesc());// 企业付款描述信息
//			enterPrisePaymentBean.setSpbill_create_ip(wxPayBill.getIp());// 操作ip
//			logger.info("WxPayBillServiceImpl/insertPayBill/enterPrisePaymentBean:{}",
//					JSON.toJSON(enterPrisePaymentBean));
//
//			// 生成红包数据签名
//			String sign = EnterPrisePaymentBean.createEnterPrisePaymentOrderSign(enterPrisePaymentBean);
//			logger.info("WxPayBillServiceImpl/insertPayBill/sign:{}", sign);
//			enterPrisePaymentBean.setSign(sign);
//
//			String respXml = BeanToXmlUtil.EnterPrisePaymentToXml(enterPrisePaymentBean);
//			logger.info("WxPayBillServiceImpl/insertPayBill/respXml:{}", respXml);
//
			Map<String, String> map = null;
//
//			map = wxServiceFacade.createEnterPrisePayment(respXml);
			logger.info("insertPayBill outerTradeNo:{},map:{}", outerTradeNo, JSON.toJSONString(map));
			// 通信标识
			String return_code = map.get("return_code");
			// 业务结果
			String result_code = map.get("result_code");
			if ("SUCCESS".equals(return_code)) {
				wxPayBill.setReturnCode(return_code);
				if ("SUCCESS".equals(result_code)) {
					wxPayBill.setResultCode(result_code);
					wxPayBill.setPaymentNo(map.get("payment_no"));
					wxPayBill.setPaymentTime(DateUtils.parseDate(map.get("payment_time"), "yyyy-MM-dd HH:mm:ss"));
					logger.info("WxPayBillServiceImpl企业付款成功");
					msg = "领取成功";
				} else {
					// 错误代码
					String err_code = map.get("err_code");
					// 错误代码描述
					String err_code_des = map.get("err_code_des");
					// 系统异常，重试
					if ("SYSTEMERROR".equals(err_code)) {
						// 存在系统异常，返回成功，进入失败队列处理
						logger.info("insertPayBill outerTradeNo:{},openId:{}", outerTradeNo, openId);
						// 放入失败队列重试
						RedisUtil.lpush(RedisKeyConstants.WX_ENTERPRISE_PAY_FAIL_QUEUE, tradeNo);
					} else {
						status = RetConstants.ERROR;
					}
					msg = err_code_des;
					wxPayBill.setErrCode(err_code);
					wxPayBill.setErrCodeDesc(err_code_des);
				}
			} else {
				// 返回信息
				String return_msg = map.get("return_msg");
				wxPayBill.setReturnMsg(return_msg);
				// 业务结果
				status = RetConstants.ERROR;
				if ("FAIL".equals(result_code)) {
					// 错误代码
					String err_code = map.get("err_code");
					// 错误代码描述
					String err_code_des = map.get("err_code_des");
					msg = return_msg;
					wxPayBill.setErrCode(err_code);
					wxPayBill.setErrCodeDesc(err_code_des);
				}
			}
			if (payBill == null) {
				this.insert(wxPayBill);
			} else {
				payBill.setErrCode(wxPayBill.getErrCode());
				payBill.setErrCodeDesc(wxPayBill.getErrCodeDesc());
				payBill.setResultCode(wxPayBill.getResultCode());
				payBill.setPaymentNo(wxPayBill.getPaymentNo());
				payBill.setPaymentTime(wxPayBill.getPaymentTime());
				this.update(payBill);
			}
			// 增加红包操作详情记录
			WxPayDetail wxPayDetail = new WxPayDetail(wxPayBill.getOuterAppid(), wxPayBill.getOuterTradeNo(),
					wxPayBill.getOuterOpenid(), "", result_code, msg, wxPayBill.getPaymentNo());
			wxPayDetailService.insert(wxPayDetail);
		} catch (Exception e) {
			e.printStackTrace();
			return new ReturnContent<>(RetConstants.SYSTEM_ERROR, RetConstants.SYSTEM_ERROR_MSG);
		}
		return new ReturnContent<>(status, msg, tradeNo);
	}

	@Override
	public void updateOpenId(WxPayBill wxPayBill) {
		wxPayBillMapper.updateOpenId(wxPayBill);
	}

	@Override
	public List<WxPayBill> findPayBillByOutOpenId(String activityId, String outerOpenid) {
		return wxPayBillMapper.findPayBillByOutOpenId(activityId, outerOpenid);
	}
}
